using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using DomainModel.Abstract;
using DomainModel.Entities;

namespace WebSite.Controllers
{
    [Authorize(Roles = "StaffingExpert")]
    // The Controller for dealing with views regarding the creation and editing of questions
    // and the answers that attach to them.
    public class QuestionsController : Controller
    {
        // The database abstractions for the questions, answers, answeredQuestions, and questionnaireEntries.
        private IQuestionsRepository questionsRepository;
        private IAnswersRepository answersRepository;
        private IAnsweredQuestionsRepository answeredQuestionsRepository;
        private IQuestionnaireEntriesRepository questionnaireEntriesRepository;

        // Constructor, it attachs the questions repository, the answers repository,
        // and the answeredQuestions repository, and the questionnaireEntries repository 
        // to the controller and it instantiates the answers data to a blank list.
        public QuestionsController(IQuestionsRepository questionsRepository, IAnswersRepository answersRepository,
                                    IAnsweredQuestionsRepository answeredQuestionsRepository, 
                                    IQuestionnaireEntriesRepository questionnaireEntriesRepository)
        {
            this.questionsRepository = questionsRepository;
            this.answersRepository = answersRepository;
            this.answeredQuestionsRepository = answeredQuestionsRepository;
            this.questionnaireEntriesRepository = questionnaireEntriesRepository;

            ViewData["answers"] = new List<Answer>();
            TempData["error"] = "";
        }

        // This is just a wrapper for the query to get a question given an id.
        private Question GetQuestion(int questionID)
        {
            Question question = (from q in questionsRepository.Questions
                                 where q.QuestionID == questionID
                                 select q).First();
            return question;
        }

        // This is just a wrapper for the query to get a answer given an id.
        private Answer GetAnswer(int answerID)
        {
            Answer answer = (from a in answersRepository.Answers
                             where a.AnswerID == answerID
                             select a).First();
            return answer;
        }

        // Provides list of questions in repository as model to Index view.
        public ActionResult Index()
        {
            return View(questionsRepository.Questions.ToList());
        }

        // Instantiates a new question and passes it to the Edit view.
        public ActionResult CreateQuestion()
        {
            return View("EditQuestion", new Question());
        }

        // Instantiates a new answer and passes it to the Edit view.
        public ActionResult CreateAnswer(int questionID)
        {
            Answer answer = new Answer();
            answer.QuestionID = questionID;
            return View("EditAnswer", answer);
        }

        // Edit command for http get, returns a question given an id
        // and passes the question to the view.
        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult EditQuestion(int questionID)
        {
            Question question = GetQuestion(questionID);

            if (question.Question_Type == 1)
                TempData["IsChecked"] = "true";

            return View(question);
        }

        // Edit command for post, places a question from the view into
        // the repository.
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult EditQuestion(Question question)
        {
            if (ModelState.IsValid)
            {
                question.Question_Type = 0;
                // This stuff is just to see if the user checked the
                // is essay option as I can't use the automatice
                // stuff to do that.
                var checkbox = Request.Form["TypeCheckbox"];
                if (checkbox != "false")
                    question.Question_Type = 1;
                else
                    question.Question_Type = 0;
                questionsRepository.SaveQuestion(question);
                return RedirectToAction("Index");
            }
            else
            {
                return View(question);
            }
        }

        // Edit command for http get, returns a answer given an id
        // and passes the answer to the view.
        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult EditAnswer(int answerID)
        {
            Answer answer = GetAnswer(answerID);

            return View(answer);
        }

        // Edit command for post, places a answer from the view into
        // the repository.
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult EditAnswer(Answer answer)
        {
            if (ModelState.IsValid)
            {
                answersRepository.SaveAnswer(answer);
                return RedirectToAction("Index");
            }
            else
            {
                return View(answer);
            }
        }

        // This utilizes an Ajax call to send the answers for the 
        // selected question to a partial view, and then redraw the
        // partial view.
        public ActionResult ViewAnswers(int questionID)
        {
            Question question = GetQuestion(questionID);
            ViewData["answers"] = question.Answers;

            return PartialView("AnswersTable", ViewData["answers"]);
        }

        // The Http-Get for delete question. Provide answer to be deleted
        // to the view.
        public ActionResult DeleteQuestion(int questionID)
        {
            Question question = GetQuestion(questionID);

            return View(question);
        }

        // This deletes a question from the repository given a
        // questionID from the view. Also deletes answers attached
        // to the question and any links between jobs and this question.
        // If there are any answeredQuestions pointing to it will not
        // delete anything.
        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult DeleteQuestion(int questionID, string qConfirmButton)
        {
            Question question = GetQuestion(questionID);

            foreach (Answer a in question.Answers)
            {
                if (a.AnsweredQuestions.Count > 0)
                {
                    TempData["error"] = "Cannot delete this question. It has important archival data attached to it.";
                    return RedirectToAction("Index");
                }
            }

            foreach (QuestionnaireEntry qe in question.QuestionnaireEntries)
            {
                if (qe.AnsweredQuestions.Count > 0)
                {
                    // Throw error.
                    return RedirectToAction("Index");
                }
            }

            foreach (Answer a in answersRepository.Answers)
            {
                if (a.QuestionID == questionID)
                {
                    answersRepository.DeleteAnswer(a);
                }
            }

            foreach (QuestionnaireEntry qe in questionnaireEntriesRepository.QuestionnaireEntries)
            {
                if (qe.QuestionID == questionID)
                {
                    questionnaireEntriesRepository.DeleteQuestionnaireEntry(qe);
                }
            }
            
            questionsRepository.DeleteQuestion(question);
            return RedirectToAction("Index");
        }

        // The Http-Get for delete answer. Provide answer to be deleted
        // to the view.
        public ActionResult DeleteAnswer(int answerID)
        {
            Answer answer = GetAnswer(answerID);

            return View(answer);
        }

        // This deletes a answer from the repository given a
        // answerID from the view. If there are any answeredQuestions
        // pointing to it then it won't delete the answer.
        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult DeleteAnswer(int answerID, string aConfirmButton)
        {
            Answer answer = GetAnswer(answerID);

            if (answer.AnsweredQuestions.Count > 0)
            {
                TempData["error"] = "Cannot delete this answer. It has important archival data attached to it.";
               return RedirectToAction("Index");
            }
            
            answersRepository.DeleteAnswer(answer);
            return RedirectToAction("Index");
        }
    }
}
